
package coreEngine;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.concurrent.TimeUnit;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
import jssc.SerialPortList;
import main.SatelliteTracker;

public class ArduinoConnector {

	private String portCom;
	private SerialPort serialPort;
	private boolean connectionIsOpen;
	private SatelliteTracker st;
	private JFrame comFrame;
	private Container container;
	private JButton chooseButton;
	private JComboBox<String> comComboBox;
	private String[] portNames;

	private int Azimuth = 0;
	private int Elevation = 0;

	public ArduinoConnector(SatelliteTracker st){
		connectionIsOpen = false;
		this.st = st;
	}

	public boolean isArduinoConnected(){
		return connectionIsOpen;
	}

	public SatelliteTracker getSatelliteTracker(){
		return st;
	}

	public SerialPort getSerialPort() {
		return serialPort;
	}
	
	public boolean getConnectionIsOpen(){
		return connectionIsOpen;
	}

	/**
	 * Comeca a ligacao ao arduino
	 * @throws SerialPortException 
	 */
	public void connectToArduino(){
		if(!connectionIsOpen){
			try {
				getSerialPort().openPort();
				connectionIsOpen = true;
				st.appendText("[INFO] Connection with "+portCom+" started");
				serialPort.setParams(SerialPort.BAUDRATE_9600, 
						SerialPort.DATABITS_8,
						SerialPort.STOPBITS_1,
						SerialPort.PARITY_NONE);   
				TimeUnit.MILLISECONDS.sleep(2200);
				int mask = SerialPort.MASK_RXCHAR + SerialPort.MASK_CTS + SerialPort.MASK_DSR;//Prepare mask
				serialPort.setEventsMask(mask);//Set mask

			} catch (SerialPortException | InterruptedException e) {
				st.appendText("[ERROR] - Impossible to communicate with "+getSerialPort());
			}

			try {
				serialPort.addEventListener(new SerialPortEventListener() {

					@Override
					public void serialEvent(SerialPortEvent event) {
						try {
							Thread.sleep(500);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						if (event.isRXCHAR()) {//If data is available
							//TODO criar uma metodo para ler os dados correctamente
							readData();
							//							System.out.println("Mensagem: "+event.toString());
						}
						else if (event.isCTS()) {//If CTS line has changed state
							if (event.getEventValue() == 1) {//If line is ON
								System.out.println("CTS - ON");
							} else {
								System.out.println("CTS - OFF");
							}
						} 
						else if (event.isDSR()) {///If DSR line has changed state
							if (event.getEventValue() == 1) {//If line is ON
								System.out.println("DSR - ON");
							} else {
								System.out.println("DSR - OFF");
							}
						}

					}
				});
			} catch (SerialPortException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	public void closeConnection(){
		if(connectionIsOpen){
			try {
				getSerialPort().closePort();
				st.appendText("[INFO] Connection with "+portCom+" stopped");
				connectionIsOpen = false;
			} catch (SerialPortException e) {
				e.printStackTrace();
			}
		}
	}

	public void sendData(String data){
		String[] aux = data.split("_");
		float az = Float.parseFloat(aux[0]);
		float el = Float.parseFloat(aux[1]);

		int vals[] = {(int) az,(int)((int)az-az)*100,(int) el,(int)((int)el-el)*100};
		ByteBuffer byteBuffer = ByteBuffer.allocate(vals.length * 4);        
        IntBuffer intBuffer = byteBuffer.asIntBuffer();
        intBuffer.put(vals);
        byte[] array = byteBuffer.array();
		try {
			System.out.println(array[3]);
			getSerialPort().writeBytes(array);
		} catch (SerialPortException e) {
			e.printStackTrace();
			
		}
	}

	/**
	 * M�todo que l� os dados do Arduino 
	 */
	public void readData() {
		 
		try {
			String DATA = serialPort.readString();
			System.out.println(DATA);
			
			String[] arduinoData = DATA.split("_");
			if(arduinoData[0].charAt(0) == '|') {
				try{
					if (Azimuth != (int)Double.parseDouble(arduinoData[0].substring(1))){
						Azimuth = (int)Double.parseDouble(arduinoData[0].substring(1));
						st.appendText("[ANTENNA] Position update: Azimuth = " + Azimuth + " Elevation = " + Elevation);
					}
				}catch(NumberFormatException e){
					e.printStackTrace();
				}
			}
			if(arduinoData[1].charAt(arduinoData[1].length()-1) == '|') {
				try{
					if(Elevation != (int)Double.parseDouble(arduinoData[1].substring(0,arduinoData[1].length()-1))){
						Elevation = (int)Double.parseDouble(arduinoData[1].substring(0,arduinoData[1].length()-1));
						st.appendText("[ANTENNA] Position update: Azimuth = " + Azimuth + " Elevation = " + Elevation);
					}
				}catch(NumberFormatException e){
					e.printStackTrace();
				}
			}

		} catch (SerialPortException e) {
			e.printStackTrace();
		}
	}



	public void init(){
		comFrame = new JFrame("Serial Port");
		comFrame.setSize(290, 130);
		comFrame.setLocationRelativeTo(null);
		comFrame.setResizable(false);
		container = comFrame.getContentPane();
		container.setLayout(new BorderLayout());



		JPanel comTextPanel = new JPanel();
		JLabel comLabel = new JLabel("Choose Arduino SerialPort:");
		comTextPanel.add(comLabel);

		comComboBox = new JComboBox<String>(portNames);
		JPanel comboPanel = new JPanel();
		comboPanel.add(comComboBox);

		container.add(comTextPanel,BorderLayout.NORTH);
		container.add(comboPanel,BorderLayout.CENTER);

		JPanel buttonPanel = new JPanel();
		chooseButton = new JButton("Choose");
		buttonPanel.add(chooseButton);
		chooseButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				serialPort = new SerialPort(portNames[comComboBox.getSelectedIndex()]);
				portCom = serialPort.getPortName();
				comFrame.setVisible(false);
				connectToArduino();
				//st.getArduinoConnectorButton().setEnabled(false);

			}
		});

		container.add(buttonPanel,BorderLayout.SOUTH);


		comFrame.setVisible(true);

	}

	//Devolve as portas COM para um array
	public void printComPorts(){
		portNames = SerialPortList.getPortNames();
	}

	public void startConnection(){
		printComPorts();

		if (portNames.length==0){
			st.appendText("[INFO]No COM ports available");
		}
		if (portNames.length==1){
			serialPort = new SerialPort(portNames[0]);
			portCom = serialPort.getPortName();
			connectToArduino();
			st.appendText("[INFO]Established connection with port "+portCom);
			//st.getArduinoConnectorButton().setEnabled(false);
		}
		else if(portNames.length>1){
			init();
		}
	}




}
